package com.yrd.common.handler;

public class MessageQueue {
	volatile boolean alive;
	Message root;
	
	public MessageQueue() {
		alive=true;
	}
	
	synchronized void add(Message message,long time){
		message.when = time;
		if(root==null){
			root = message;
		}else{
			Message tmpmsg = root;
			Message premsg=null;
			while(tmpmsg!=null){
				if(time < tmpmsg.when){
					if(premsg==null){
						message.nextMessage = tmpmsg;
						root = message;
					}else{
						message.nextMessage = tmpmsg;
						premsg.nextMessage = message;
					}
					break;
				}else{
					premsg = tmpmsg;
					tmpmsg = tmpmsg.nextMessage;
				}
			}
			if(tmpmsg==null){
				premsg.nextMessage=message;
				message.nextMessage=null;
			}
			
		}
		notify();
	}
	
	boolean equalMessage(int type,Object object,Message message){
		if(type==Message.TYPE_MESSAGE){
			return object == message;
		}else if(type==Message.TYPE_RUNNABLE){
			return object == message.runnable;
		}else if(type==Message.TYPE_CALLABLE){
			return object == message.callable;
		}
		return false;
	}
	
	synchronized void remove(Handler handle,Object object,int type){
		if(root==null) return;
		Message tmpmsg = root;
		Message premsg=null;
		while(tmpmsg!=null){
			if(tmpmsg.handle == handle && equalMessage(type,object,tmpmsg)){
				if(premsg==null){
					tmpmsg = tmpmsg.nextMessage;
					root = tmpmsg;
				}else{
					tmpmsg = tmpmsg.nextMessage;
					premsg.nextMessage = tmpmsg;
				}
			}else{
				premsg = tmpmsg;
				tmpmsg = tmpmsg.nextMessage;
			}
		}
		notify();
	}
	
	synchronized Message next(){
		Message msg=null;
		while(alive){
			if(root==null){
				try {
					wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}else{
				long now = System.currentTimeMillis();
				if(root.when <= now){
					msg=root;
					root = root.nextMessage;
					break;
				}else{
					long delay = root.when - now; 
					try {
						wait(delay);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}
		return msg;
	}
	
	synchronized void quit() throws InterruptedException{
		alive=false;
		notify();
	}
	
}
